package com.gitee.srurl.core.api.impl.disable;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.gitee.srurl.core.annotation.ApiImpl;
import com.gitee.srurl.core.api.IDisabledStrategy;
import com.gitee.srurl.core.constant.ApiTypeConstant;
import lombok.extern.slf4j.Slf4j;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 黑名单禁止策略
 *
 * @author zxw
 * @date 2023/4/19 22:56
 */
@Slf4j
@ApiImpl(ApiTypeConstant.DisableStrategy.BLACKLIST)
public class BlacklistDisabledStrategy implements IDisabledStrategy {

    private static final Set<String> blacklistCache = new HashSet<>();

    private static final ReadWriteLock lock = new ReentrantReadWriteLock();
    private static final Lock wLock = lock.writeLock();
    private static final Lock rLock = lock.readLock();

    @Override
    public boolean disabled(String originUrl) {

        if (StrUtil.isBlank(originUrl)) {
            // 地址有问题 不进行后续操作
            return true;
        }

        rLock.lock();
        try {
            URI uri = URLUtil.getHost(new URL(originUrl));
            String host = uri.getHost();
            return blacklistCache.contains(host);
        } catch (MalformedURLException e) {
            log.error("获取host失败,url:{},ex:", originUrl, e);
            return true;
        } finally {
            rLock.unlock();
        }
    }

    /**
     * 更新缓存
     *
     * @param blacklist 黑名单列表
     * @param status    true:添加，false:解除
     */
    public static synchronized void updateCache(Set<String> blacklist, boolean status) {

        wLock.lock();
        try {
            if (!status) {
                blacklistCache.removeAll(blacklist);
            } else {
                blacklistCache.addAll(blacklist);
            }
        } finally {
            wLock.unlock();
        }
    }

    public static synchronized void updateCache(String blacklist, boolean status) {

        wLock.lock();
        try {
            if (!status) {
                blacklistCache.remove(blacklist);
            } else {
                blacklistCache.add(blacklist);
            }
        } finally {
            wLock.unlock();
        }
    }
}
